class Node {
    constructor(id, x, y, inputs = [0], outputs = [0]) {
        this.id = id;
        this.x = x;
        this.y = y;
        this.inputs = inputs;
        this.outputs = outputs;
        this.element = this.createElement();
    }

    createElement() {
        const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
        g.setAttribute("class", "node");
        g.setAttribute("transform", `translate(${this.x}, ${this.y})`);
        g.setAttribute("data-id", this.id);

        const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
        rect.setAttribute("width", 100);
        rect.setAttribute("height", 50);
        rect.setAttribute("fill", "#f0f0f0");
        rect.setAttribute("stroke", "#333");
        rect.setAttribute("stroke-width", 2);
        g.appendChild(rect);

        this.inputs.forEach((input, index) => {
            const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
            circle.setAttribute("cx", -5);
            circle.setAttribute("cy", 25 + index * 15);
            circle.setAttribute("r", 5);
            circle.setAttribute("class", "connector");
            g.appendChild(circle);
        });

        this.outputs.forEach((output, index) => {
            const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
            circle.setAttribute("cx", 105);
            circle.setAttribute("cy", 25 + index * 15);
            circle.setAttribute("r", 5);
            circle.setAttribute("class", "connector");
            g.appendChild(circle);
        });

        return g;
    }
}

class Line {
    constructor(id, fromNode, fromIndex, toNode, toIndex) {
        this.id = id;
        this.fromNode = fromNode;
        this.fromIndex = fromIndex;
        this.toNode = toNode;
        this.toIndex = toIndex;
        this.element = this.createElement();
    }

    createElement() {
        const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line.setAttribute("stroke", "#333");
        line.setAttribute("stroke-width", 2);
        this.updatePosition();
        return line;
    }

    updatePosition() {
        if (!this.fromNode || !this.toNode) {
            console.error(`Invalid nodes: fromNode=${this.fromNode}, toNode=${this.toNode}`);
            return;
        }

        const fromX = this.fromNode.x + 100;
        const fromY = this.fromNode.y + 25 + this.fromIndex * 15;
        const toX = this.toNode.x;
        const toY = this.toNode.y + 25 + this.toIndex * 15;

        this.element.setAttribute("x1", fromX);
        this.element.setAttribute("y1", fromY);
        this.element.setAttribute("x2", toX);
        this.element.setAttribute("y2", toY);
    }
}

class NodeFactory {
    static createNode(config) {
        return new Node(config.id, config.x, config.y, config.inputs, config.outputs);
    }

    static createNodesFromConfig(configs) {
        return configs.map(config => this.createNode(config));
    }
}

class App {
    constructor(svgCanvasId) {
        this.svgCanvas = document.getElementById(svgCanvasId);
        this.nodes = [];
        this.lines = [];
        this.init();
    }

    init() {
        // 示例节点配置
        const nodeConfigs = [
            { id: 1, type: 'type1', x: 100, y: 100, inputs: [0], outputs: [0, 1] },
            { id: 2, type: 'type2', x: 300, y: 100, inputs: [0, 1], outputs: [0] }
        ];

        this.nodes = NodeFactory.createNodesFromConfig(nodeConfigs);
        this.nodes.forEach(node => this.svgCanvas.appendChild(node.element));

        const fromNode = this.nodes.find(node => node.id === 1);
        const toNode = this.nodes.find(node => node.id === 2);

        if (!fromNode || !toNode) {
            console.error('Error: Invalid node IDs in line configuration');
            return;
        }

        this.lines = [
            new Line(1, fromNode, 0, toNode, 0)
        ];
        this.lines.forEach(line => this.svgCanvas.appendChild(line.element));

        this.enableDragging();
    }

    enableDragging() {
        this.nodes.forEach(node => {
            node.element.addEventListener('mousedown', (event) => {
                event.preventDefault();
                const onMouseMove = (e) => {
                    const dx = e.movementX;
                    const dy = e.movementY;
                    node.x += dx;
                    node.y += dy;
                    node.element.setAttribute('transform', `translate(${node.x}, ${node.y})`);
                    this.updateLines();
                };

                const onMouseUp = () => {
                    document.removeEventListener('mousemove', onMouseMove);
                    document.removeEventListener('mouseup', onMouseUp);
                };

                document.addEventListener('mousemove', onMouseMove);
                document.addEventListener('mouseup', onMouseUp);
            });
        });
    }

    updateLines() {
        this.lines.forEach(line => line.updatePosition());
    }
}

document.addEventListener('DOMContentLoaded', () => {
    new App('svgCanvas');
});
